package cn.iocoder.yudao.module.erp.service.secstock;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.erp.common.InventoryTurnover;
import cn.iocoder.yudao.module.erp.controller.admin.secaccount.vo.SecAccountRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.secaccount.vo.SecHisAccountRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.warehouserule.vo.WarehouseRulePageReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.checkout.CheckOutItemDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.pristock.PriStockDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.secaccount.SecAccountDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehouseinlist.WarehouseInListDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehouseoutlist.WarehouseOutListDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehouserule.WarehouseRuleDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.warningrules.WarningRulesDO;
import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.secaccount.SecAccountMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.warningrules.WarningRulesMapper;
import cn.iocoder.yudao.module.erp.service.warehouserule.WarehouseRuleServiceImpl;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.erp.controller.admin.secstock.vo.*;
import cn.iocoder.yudao.module.erp.dal.dataobject.secstock.SecStockDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.erp.dal.mysql.secstock.SecStockMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;

/**
 * ERP 二级库库存 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class SecStockServiceImpl implements SecStockService {

    @Resource
    private SecStockMapper secStockMapper;
    @Resource
    private SecAccountMapper secAccountMapper;
    @Resource
    private WarningRulesMapper warningRulesMapper;
    @Resource
    private WarehouseRuleServiceImpl warehouseRuleService;
    @Resource
    private AdminUserMapper adminUserMapper;
    @Resource
    private DeptMapper deptMapper;
    @Resource
    private InventoryTurnover inventoryTurnover;

    @Autowired
    private ErpProductMapper erpProductMapper;

    @Override
    public Long createSecStock(SecStockSaveReqVO createReqVO) {
        // 插入
        SecStockDO secStock = BeanUtils.toBean(createReqVO, SecStockDO.class);
        secStockMapper.insert(secStock);
        // 返回
        return secStock.getId();
    }

    @Override
    public void updateSecStock(SecStockSaveReqVO updateReqVO) {
        // 校验存在
        validateSecStockExists(updateReqVO.getId());
        // 更新
        SecStockDO updateObj = BeanUtils.toBean(updateReqVO, SecStockDO.class);
        secStockMapper.updateById(updateObj);
    }

    @Override
    public void deleteSecStock(Long id) {
        // 校验存在
        validateSecStockExists(id);
        // 删除
        secStockMapper.deleteById(id);
    }

    private void validateSecStockExists(Long id) {
        if (secStockMapper.selectById(id) == null) {
            throw exception(SEC_STOCK_NOT_EXISTS);
        }
    }

    @Override
    public SecStockDO getSecStock(Long id) {
        return secStockMapper.selectById(id);
    }

    //    根据 deptId 查询 ERP 二级库库存
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<SecStockDO> getSecStockByDeptId(List<Integer> type, String Sname, String deptId) {

//        Sname 不等于空或不为undefined才执行
        if ("null".equals(Sname) || Sname.equals("undefined")) {
            Sname = null;
        } else {
            Sname = Sname + "%";
        }
        // 处理 deptId
        Long deptIdLong = null;
        if (deptId != null && !"null".equals(deptId) && !"undefined".equals(deptId)) {
            try {
                deptIdLong = Long.parseLong(deptId);
            } catch (NumberFormatException e) {
                // 处理转换失败的情况，例如记录日志或抛出自定义异常
                throw new IllegalArgumentException("Invalid deptId value: " + deptId, e);
            }
        }
//        按出入库规则筛选产品（传0返回rule==1 为按效期先出）
        PageResult<WarehouseRuleDO> warehouseRulePage = warehouseRuleService.getWarehouseRulePage(new WarehouseRulePageReqVO().setRuleType("0"));
//        String ruleTypeStr = String.join(",", ruleType);
        String rule = warehouseRulePage.getList().stream().map(WarehouseRuleDO::getRule).collect(Collectors.toList()).get(0);
        List<SecStockDO> secStockByDeptId = secStockMapper.getSecStockByDeptId(type, Sname, rule, deptIdLong);
//        实现把secStockByDeptId数据中的产品名 后面拼接产品规格
        for (SecStockDO secStockDO : secStockByDeptId) {
            String productName = secStockDO.getProductName();
            String productStandards = secStockDO.getProductStandards();
            secStockDO.setProductName(productName + "   " + productStandards);
        }
        return secStockByDeptId;

    }


    @Override
    public PageResult<SecStockDO> getSecStockPage(SecStockPageReqVO pageReqVO) {
        PageResult<SecStockDO> secStockDOPageResult = secStockMapper.selectPage(pageReqVO);
        if (secStockDOPageResult.getTotal() == 0) {
            return secStockDOPageResult;
        } else {
            //设置创建者的名
            List<String> creatorList = secStockDOPageResult.getList().stream().map(SecStockDO::getCreator).collect(Collectors.toList());
            List<AdminUserDO> adminUserDOS = adminUserMapper.selectList(new QueryWrapper<AdminUserDO>().in("id", creatorList));
            Map<String, String> creatorMap = adminUserDOS.stream().collect(Collectors.toMap(user -> String.valueOf(user.getId()), AdminUserDO::getNickname));
            secStockDOPageResult.getList().forEach(secStockDO -> {
                secStockDO.setCreator(creatorMap.get(secStockDO.getCreator()));
            });
        }
        return secStockDOPageResult;
    }


    @Override
    public List<SecStockRespVO> getSecStockVOList(Collection<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return Collections.emptyList();
        }
        List<SecStockDO> list = secStockMapper.selectBatchIds(ids);
        return buildSecStockVOList(list);
    }

    private List<SecStockRespVO> buildSecStockVOList(List<SecStockDO> list) {
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        return BeanUtils.toBean(list, SecStockRespVO.class, secStock -> {

        });
    }

    @Override
    public List<String> getBatchsByProductId(Long productId) {
        return secStockMapper.selectBatchsByProductId(productId);
    }

    @Override
    public SecStockDO getProductByBatch(Long productId, String productBatch) {
        return secStockMapper.selectByProductIdAndBatch(productId, productBatch);
    }

    @Override
    public List<SecStockDO> getsecStockList() {
        return secStockMapper.selectList();
    }

    @Override
    public void updateSecStockCount(SecStockDO productByBatch) {
        secStockMapper.updateSecStockCount(productByBatch);

    }

    @Override
    public List<SecStockDO> getProductsByBatch(List<SecStockDO> collect) {
        return secStockMapper.selectByBatch(collect);
    }

    @Override
    public void updateSecStockCountBatch(List<SecStockDO> stocksToUpdate) {
        secStockMapper.updateSecstockCountBatch(stocksToUpdate);
    }

    @Override
    public PageResult<SecStockDO> getSecStockPageByDetain(SecStockPageReqVO pageReqVO) {
        // 获取分页结果
        PageResult<SecStockDO> secStockDOPageResult = secStockMapper.selectPage(pageReqVO);
        List<SecStockDO> list = secStockDOPageResult.getList();
        List<SecStockDO> newList = new ArrayList<>();

        // 查询所有符合条件的警告规则
        Integer queryType = pageReqVO.getQueryType();
        List<WarningRulesDO> warningRulesDOS = warningRulesMapper.selectList(
                new QueryWrapper<WarningRulesDO>().eq("dept_id", pageReqVO.getDeptId())
        );
        // 遍历 list 和 warningRulesDOS，检查每个元素是否符合警告规则
        if (queryType == 1) {
            for (SecStockDO item : list) {
                for (WarningRulesDO rule : warningRulesDOS) {
                    if (item.getProductId().equals(rule.getProductId()) &&
                            item.getProductStandards().equals(rule.getStandard())) {
                        LocalDateTime createTime = item.getCreateTime();
                        LocalDateTime now = LocalDateTime.now();
                        long daysBetween = ChronoUnit.DAYS.between(createTime, now);
                        if (daysBetween >= rule.getDetainValue()) {
                            newList.add(item);
                            break; // 一旦匹配并添加到 newList，跳出内层循环，继续处理下一个 item
                        }
                    }
                }
            }
        } else if (queryType == 2) {
            for (SecStockDO item : list) {
                for (WarningRulesDO rule : warningRulesDOS) {
                    if (item.getProductId().equals(rule.getProductId()) &&
                            item.getProductStandards().equals(rule.getStandard())) {
                        LocalDateTime validityDate = item.getProductValidityDate();
                        LocalDateTime now = LocalDateTime.now();
                        long daysBetween = ChronoUnit.DAYS.between(now, validityDate);
                        if (daysBetween <= rule.getExpirydateValue()) {
                            newList.add(item);
                            break; // 一旦匹配并添加到 newList，跳出内层循环，继续处理下一个 item
                        }
                    }
                }
            }
        } else if (queryType == 3) {

            // 使用stream API来分组并合并相同productId和productStandards的元素
            Map<String, SecStockDO> mergedItems = list.stream()
                    .collect(Collectors.toMap(
                            // 通过复合键（productId + productStandards）来确保唯一性
                            item -> item.getProductId() + "-" + item.getProductStandards(),
                            // 保留原始的item
                            item -> item,
                            // 当键冲突时合并的逻辑
                            (existingItem, newItem) -> {
                                existingItem.setCount(existingItem.getCount().add(newItem.getCount()));
                                return existingItem;
                            }
                    ));

            // 将合并后的结果转换回List
            List<SecStockDO> resultList = new ArrayList<>(mergedItems.values());
            for (SecStockDO item : resultList) {
                for (WarningRulesDO rule : warningRulesDOS) {
                    if (item.getProductId().equals(rule.getProductId()) &&
                            item.getProductStandards().equals(rule.getStandard())) {
                        BigDecimal count = item.getCount();
                        BigDecimal maxValue = rule.getMaxValue();
                        BigDecimal minValue = rule.getMinValue();
                        if (count.compareTo(maxValue) > 0 || count.compareTo(minValue) < 0) {
                            newList.add(item);
                            break; // 一旦匹配并添加到 newList，跳出内层循环，继续处理下一个 item
                        }
                    }
                }
            }
        }


        // 更新分页结果的列表
        secStockDOPageResult.setList(newList).setTotal(Long.valueOf(newList.size()));

        // 返回更新后的分页结果
        return secStockDOPageResult;
    }

    @Override
    public List<Integer> getIds() {
        return secStockMapper.selectIds();
    }

    @Override
    public List<String> getStandardsByProductName(String productName) {
        return secStockMapper.selectStandardsByProductName(productName);
    }

    @Override
    public List<String> getInboundBatchsByProductId(Long productId, String productBatch) {
        return secStockMapper.selectInboundBatchsByProductId(productId, productBatch);
    }

    @Override
    public List<SecStockDO> getsecStockListByBatch() {
        return secStockMapper.selectListByBatch();
    }

    @Override
    public List<SecStockDO> selectStockListByProductBatch(List<SecStockDO> stocks) {
        return secStockMapper.selectStockListByProductBatch(stocks);
    }

    /**
     * HIS查询耗材二级库库存接口
     * 根据科室ID和产品ID查询库存信息
     * @param deptId
     * @param productId
     * @return
     */
    @Override
    public List<SecStockDO> getStock(String deptId, String productId) {
        return secStockMapper.selectList(new QueryWrapper<SecStockDO>().lambda().eq(SecStockDO::getDeptId, deptId).eq(SecStockDO::getProductId, productId));
    }

    @Override
    public List<SecStockRespVO> getProductIds() {
        return secStockMapper.selectProductIds();
    }

    @Override
    public void reduceStock(String deptId, String productId, int num) {
        // 实现减库存的逻辑，例如更新数据库中的库存数量
        // 这里需要根据实际的数据库操作和业务逻辑进行实现
        // 示例代码如下：
//        SecStockDO secStock = secStockMapper.getStockByDeptAndProduct(deptId, productId);
//        if (secStock != null) {
//            BigDecimal currentCount = secStock.getCount();
//            BigDecimal newCount = currentCount.subtract(BigDecimal.valueOf(num));
//            secStock.setCount(newCount);
//            secStockMapper.update(secStock);
//        }
    }

    @Override
    public List<SecHisAccountRespVO> getStockAccount(String deptId, String productId, Integer outInType, DateTime outInTimeS, DateTime outInTimeE) {
        String affairs = "";
        if (outInType != null){
            if (outInType == 1) {
                affairs = "出库";
            }else if (outInType == 2) {
                affairs = "入库";
            }
        }
        // 根据科室ID和产品ID等查询库存信息
        List<SecAccountDO> secAccountDOList = secAccountMapper.getStock(deptId, productId, affairs, outInTimeS, outInTimeE);
        // 转换为RespVO对象
        List<SecAccountRespVO> secAccountRespVOList = BeanUtils.toBean(secAccountDOList, SecAccountRespVO.class);
        // 获取科室信息
        List<DeptDO> deptDOS = deptMapper.selectList();
        // 获取产品信息
        for (SecAccountRespVO secAccountRespVO : secAccountRespVOList) {
            Long fromDeptId = secAccountRespVO.getFromDeptId();
            Long toDeptId = secAccountRespVO.getToDeptId();
            Long deptId2 = secAccountRespVO.getDeptId();
            for (DeptDO deptDO : deptDOS) {
                if (fromDeptId.equals(deptDO.getId())) {
                    secAccountRespVO.setFromDeptName(deptDO.getName());
                }
                if (toDeptId.equals(deptDO.getId())) {
                    secAccountRespVO.setToDeptName(deptDO.getName());
                }
                if (deptId2.equals(deptDO.getId())) {
                    secAccountRespVO.setDeptName(deptDO.getName());
                }
                // 如果secAccountRespVO的DeptId,FromDeptName和ToDeptName值不为空，则跳出循环
                if (secAccountRespVO.getDeptName() != null && secAccountRespVO.getFromDeptName() != null && secAccountRespVO.getToDeptName() != null) {
                    break;
                }
            }
        }
        // 转换为HisAccountRespVO对象
        List<SecHisAccountRespVO> secHisAccountRespVOList = BeanUtils.toBean(secAccountRespVOList, SecHisAccountRespVO.class);
        // 遍历secHisAccountRespVOList 给outInType赋值
        for (SecHisAccountRespVO secHisAccountRespVO : secHisAccountRespVOList) {
            secHisAccountRespVO.setOutInType(secHisAccountRespVO.getAffairs());
        }
        return secHisAccountRespVOList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Integer> sellProduct(List<Map<String, String>> sellList) {
        Map<String, Integer> resultMap = new HashMap<>();

        // 收集所有需要查询的 deptId 和 productId 组合
        List<Map<String, String>> paramList = new ArrayList<>();
        for (Map<String, String> sellMap : sellList) {
            String deptId = sellMap.get("deptId");
            String productId = sellMap.get("productId");
            Map<String, String> param = new HashMap<>();
            param.put("deptId", deptId);
            param.put("productId", productId);
            paramList.add(param);
        }

        // 一次性查询所有相关的库存记录
        List<SecStockDO> allStocks = secStockMapper.getStockByDeptAndProductBatchList(paramList);
        Map<String, List<SecStockDO>> stockMap = new HashMap<>();
        for (SecStockDO stock : allStocks) {
            String key = stock.getDeptId() + "_" + stock.getProductId();
            stockMap.computeIfAbsent(key, k -> new ArrayList<>()).add(stock);
        }
        System.out.println("stockMap" + stockMap);

        List<SecStockDO> updatedStocks = new ArrayList<>();
        List<SecAccountDO> accountRecords = new ArrayList<>(); // 新增的二级库存台账记录列表

        // 存储每个 deptId 对应的出库单编号
        Map<String, String> deptOutIdMap = new HashMap<>();

        // 为每个不同的 deptId 生成出库单
        Set<String> deptIds = new HashSet<>();
        for (Map<String, String> sellMap : sellList) {
            String deptId = sellMap.get("deptId");
            deptIds.add(deptId);
        }
        for (String deptId : deptIds) {
            WarehouseOutListDO warehouseOutListDO = new WarehouseOutListDO();
            warehouseOutListDO.setInDeptId(deptId);
            warehouseOutListDO.setOutDeptId(deptId);
            String outId = inventoryTurnover.creatWarehouseOutList(warehouseOutListDO);
            deptOutIdMap.put(deptId, outId);
        }

        for (Map<String, String> sellMap : sellList) {
            String deptId = sellMap.get("deptId");
            String productId = sellMap.get("productId");
            int num = Integer.parseInt(sellMap.get("num"));
            String key = deptId + "_" + productId;
            List<SecStockDO> stocks = stockMap.getOrDefault(key, Collections.emptyList());
            int remainingNum = num;

            for (SecStockDO stock : stocks) {
                if (remainingNum <= 0) {
                    break;
                }
                BigDecimal currentCount = stock.getCount();
                BigDecimal changeCount = BigDecimal.ZERO; // 记录库存变化量

                if (currentCount.compareTo(BigDecimal.valueOf(remainingNum)) >= 0) {
                    // 库存足够，直接减少库存
                    BigDecimal newCount = currentCount.subtract(BigDecimal.valueOf(remainingNum));
                    changeCount = BigDecimal.valueOf(remainingNum).negate();
                    stock.setCount(newCount);
                    remainingNum = 0;
                } else {
                    // 库存不足，将当前库存减为 0
                    changeCount = currentCount.negate();
                    stock.setCount(BigDecimal.ZERO);
                    remainingNum -= currentCount.intValue();
                }
                updatedStocks.add(stock);

                // 创建二级库存台账记录
                SecAccountDO secAccountDO = BeanUtils.toBean(stock, SecAccountDO.class);
                secAccountDO.setDeptId(Long.valueOf(deptId));
                secAccountDO.setFromDeptId(Long.valueOf(deptId));
                secAccountDO.setToDeptId(Long.valueOf(deptId));
                secAccountDO.setAffairs("HIS售出耗材减库存");
                secAccountDO.setStatus(1); // 使用常量或枚举
                secAccountDO.setId(null);
                secAccountDO.setCreateTime(LocalDateTime.now());
                secAccountDO.setUpdateTime(null);
                secAccountDO.setCount(changeCount); // 记录库存变化量
                // 将对应 deptId 的出库单编号存入 AffairsId 字段
                secAccountDO.setAffairsId(deptOutIdMap.get(deptId));
                accountRecords.add(secAccountDO);
            }
        }

        // 批量更新库存
        if (!updatedStocks.isEmpty()) {
            int rows = secStockMapper.batchUpdateStockWithVersion(updatedStocks);
//                if (rows != 1) {
//                    // 乐观锁冲突，抛出异常或进行重试逻辑
//                    throw new RuntimeException("乐观锁冲突，库存更新失败");
//                }
        }

        // 批量插入二级库存台账记录
        if (!accountRecords.isEmpty()) {
            boolean insertResult = secAccountMapper.insertBatch(accountRecords);
            if (!insertResult) {
                throw new RuntimeException("二级库存台账记录插入失败");
            }
        }

        return resultMap;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Long> virtualCreate(List<SecStockSaveReqVO> createReqVOList) {
        // 将 SecStockSaveReqVO 转换为 SecStockDO
        List<SecStockDO> secStockDOList = createReqVOList.stream()
                .map(reqVO -> BeanUtils.toBean(reqVO, SecStockDO.class))
                .collect(Collectors.toList());
        List<Long> productIds = secStockDOList.stream().map(SecStockDO::getProductId).collect(Collectors.toList());
        List<ErpProductDO> erpProductDOS = erpProductMapper.selectList(new QueryWrapper<ErpProductDO>().in("id", productIds));
        Map<Long, ErpProductDO> productDOMap = erpProductDOS.stream().collect(Collectors.toMap(ErpProductDO::getId, ErpProductDO -> ErpProductDO));

        // 查询已存在的二级库库存
        List<SecStockDO> existingSecStocks = secStockMapper.selectList(new QueryWrapper<SecStockDO>().in("product_id", productIds));
        Map<Long, SecStockDO> existingSecStockMap = existingSecStocks.stream().collect(Collectors.toMap(SecStockDO::getProductId, secStockDO -> secStockDO));

        List<SecStockDO> toInsert = new ArrayList<>();
        List<SecStockDO> toUpdate = new ArrayList<>();

        for (SecStockDO secStockDO : secStockDOList) {
            ErpProductDO erpProductDO = productDOMap.get(secStockDO.getProductId());
            if (existingSecStockMap.containsKey(secStockDO.getProductId())) {
                // 如果存在，则更新库存数量
                SecStockDO existingSecStock = existingSecStockMap.get(secStockDO.getProductId());
                existingSecStock.setCount(existingSecStock.getCount().add(secStockDO.getCount()));
                toUpdate.add(existingSecStock);
            } else {
                // 如果不存在，则插入
                secStockDO.setProductStandards(erpProductDO.getStandard())
                        .setProductName(erpProductDO.getName())
                        .setProductUnitId(erpProductDO.getUnitId())
                        .setProductUnitName(erpProductDO.getUnitName())
                        .setProductCategoryId(erpProductDO.getCategoryId())
                        .setProductCategoryName(erpProductDO.getCategoryName())
                        .setProductPrice(erpProductDO.getPurchasePrice())
                        .setProductValidityDate(erpProductDO.getEndTime())
                        .setProductBatch("");
                toInsert.add(secStockDO);
            }
        }

        // 批量插入
        if (!toInsert.isEmpty()) {
            secStockMapper.insertBatch(toInsert);
        }

        // 批量更新
        if (!toUpdate.isEmpty()) {
            secStockMapper.updateBatch(toUpdate);
        }

        // 提取插入后的 ID 集合
        List<Long> createdIds = toInsert.stream()
                .map(SecStockDO::getId)
                .collect(Collectors.toList());

        // 提取更新后的 ID 集合
        List<Long> updatedIds = toUpdate.stream()
                .map(SecStockDO::getId)
                .collect(Collectors.toList());

        // 合并插入和更新的 ID 集合
        createdIds.addAll(updatedIds);

        return createdIds;
    }

    @Override
    public void virtualUpdate(List<SecStockSaveReqVO> updateReqVOList) {
        // 将 SecStockSaveReqVO 转换为 SecStockDO
        List<SecStockDO> secStockDOList = updateReqVOList.stream()
                .map(reqVO -> BeanUtils.toBean(reqVO, SecStockDO.class))
                .collect(Collectors.toList());
//        减库存
        subtractStock(secStockDOList);
    }


    @Override
    public void virtualPack(VirtualPackReqVO virtualPackReqVO) {
        /*先进行判断  是否有这个高职 有直接绑定 没有 要新增产品字典要新增 并推给his
        对createReqVOList中的产品 进行打包   这个包也是个  二级库插入打的包  0库存  入库表  出库表
        计费问题  高值  发票啥的     费用  价格翻倍
        * 1.手术完了 要打包时  是不得先选是那个高值包（有直接选 没有看看怎么维护） 然后在进行绑定
        * 2.入库单 出库单 台账 存 包 还是存零件
        * 3.有没有批次的问题
        * */

        // 获取请求中的产品列表
        List<SecStockSaveReqVO> virtualList = virtualPackReqVO.getVirtualList();
        List<SecStockDO> virtualDOList = virtualList.stream()
                .map(reqVO -> BeanUtils.toBean(reqVO, SecStockDO.class))
                .collect(Collectors.toList());

        // 调用封装的减库存方法
        deductStock(virtualDOList);
    }
    /**
     * 只减库存
     *
     * @param virtualDOList 需要减库存的产品列表
     *
     */
    public void subtractStock(List<SecStockDO> virtualDOList) {

        // 提取产品 ID 列表
        List<Long> productIdList = virtualDOList.stream().map(SecStockDO::getProductId).collect(Collectors.toList());

        // 根据产品 ID 获取库存列表
        List<SecStockDO> stockDOList = secStockMapper.selectList(new QueryWrapper<SecStockDO>().in("product_id", productIdList));
        // 创建一个 Map 用于快速查找库存
        Map<Long, SecStockDO> stockDOMap = stockDOList.stream()
                .collect(Collectors.toMap(SecStockDO::getProductId, stockDO -> stockDO));

        // 构建需要更新的库存列表
        List<SecStockDO> stocksToUpdate = new ArrayList<>();

        for (SecStockDO secStockDO : virtualDOList) {
            Long productId = secStockDO.getProductId();
            BigDecimal countToDeduct = secStockDO.getCount();

            // 从 stockDOMap 中获取对应的产品库存
            SecStockDO stockDO = stockDOMap.get(productId);
            if (stockDO == null) {
                throw exception(SEC_STOCK_NOT_EXISTS);
            }

            // 减去库存数量
            BigDecimal currentCount = stockDO.getCount();
            if (currentCount.compareTo(countToDeduct) < 0) {
                throw exception(CHECK_OUT_NOT_EXISTS1, stockDO.getProductName());
            }
            stockDO.setCount(currentCount.subtract(countToDeduct));
            // 添加到需要更新的列表
            stocksToUpdate.add(stockDO);
        }
//        批量更新库存
        secStockMapper.updateBatch(stocksToUpdate);
    }

    /**
     * 减库存并生成台账操作
     *
     * @param virtualDOList 需要减库存的产品列表
     *
     */
    public void deductStock(List<SecStockDO> virtualDOList) {

        //        要插入台账的集合
        List<SecAccountDO> secAccountlist = new ArrayList<>();
        // 提取产品 ID 列表
        List<Long> productIdList = virtualDOList.stream().map(SecStockDO::getProductId).collect(Collectors.toList());

        // 根据产品 ID 获取库存列表
        List<SecStockDO> stockDOList = secStockMapper.selectList(new QueryWrapper<SecStockDO>().in("product_id", productIdList));
        // 创建一个 Map 用于快速查找库存
        Map<Long, SecStockDO> stockDOMap = stockDOList.stream()
                .collect(Collectors.toMap(SecStockDO::getProductId, stockDO -> stockDO));

        // 构建需要更新的库存列表
        List<SecStockDO> stocksToUpdate = new ArrayList<>();
        Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
        //            生成出库单数据   返回出库单编号
        WarehouseOutListDO warehouseOutListDO = new WarehouseOutListDO()
                .setInDeptId(String.valueOf(loginUserDeptId))
                .setOutDeptId(String.valueOf(loginUserDeptId))
                .setOutTime(LocalDateTime.now());
        String outAffairsId = inventoryTurnover.creatWarehouseOutList(warehouseOutListDO);

        //            生成出库单数据   返回出库单编号
        WarehouseInListDO warehouseInListDO = new WarehouseInListDO()
                .setInDeptId(String.valueOf(loginUserDeptId))
                .setOutDeptId(String.valueOf(loginUserDeptId))
                .setInTime(LocalDateTime.now());
        String inAffairsId = inventoryTurnover.creatWarehouseInList(warehouseInListDO);

        for (SecStockDO secStockDO : virtualDOList) {
            Long productId = secStockDO.getProductId();
            BigDecimal countToDeduct = secStockDO.getCount();

            // 从 stockDOMap 中获取对应的产品库存
            SecStockDO stockDO = stockDOMap.get(productId);
            if (stockDO == null) {
                throw exception(SEC_STOCK_NOT_EXISTS);
            }

            // 减去库存数量
            BigDecimal currentCount = stockDO.getCount();
            if (currentCount.compareTo(countToDeduct) < 0) {
                throw exception(CHECK_OUT_NOT_EXISTS1, stockDO.getProductName());
            }
            stockDO.setCount(currentCount.subtract(countToDeduct));
            SecAccountDO secAccountDO = getSecAccountDO(countToDeduct, stockDO, loginUserDeptId,outAffairsId);
            SecAccountDO secInAccountDO = getInSecAccountDO(countToDeduct, stockDO, loginUserDeptId,inAffairsId);
            secAccountlist.add(secAccountDO);
            secAccountlist.add(secInAccountDO);
            // 添加到需要更新的列表
            stocksToUpdate.add(stockDO);
        }
//        批量更新库存
        secStockMapper.updateBatch(stocksToUpdate);
//        批量插入台账数据
        secAccountMapper.insertBatch(secAccountlist);
    }


    /**
     * 生成台账信息的方法（出库）
     * @param count     核销数
     * @param secStockDO
     * @param deptId
     * @return
     */
    private SecAccountDO getSecAccountDO(BigDecimal count, SecStockDO secStockDO, Long deptId, String AffairsId) {
        // 处理插入二级库台账的数据
        SecAccountDO secAccountDO = new SecAccountDO();
        BeanUtils.copyProperties(secStockDO, secAccountDO);
        secAccountDO.setAffairs("出库" )
                .setAffairsId(AffairsId) // 使用常量或枚举
                .setDeptId(SecurityFrameworkUtils.getLoginUserDeptId())
                .setToDeptId(deptId)
                .setFromDeptId(deptId)
                .setRemark("库存减" + count)
                .setCount(count)
                .setStatus(1) // 使用常量或枚举
                .setId(null).setCreateTime(LocalDateTime.now())
                .setUpdateTime(null);
        return secAccountDO;
    }

    /**
     * 生成台账信息的方法（入库）
     * @param count     核销数
     * @param secStockDO
     * @param deptId
     * @return
     */
    private SecAccountDO getInSecAccountDO(BigDecimal count, SecStockDO secStockDO, Long deptId, String AffairsId) {
        // 处理插入二级库台账的数据
        SecAccountDO secAccountDO = new SecAccountDO();
        BeanUtils.copyProperties(secStockDO, secAccountDO);
        secAccountDO.setAffairs("入库")
                .setAffairsId(AffairsId) // 使用常量或枚举
                .setDeptId(deptId)
                .setToDeptId(deptId)
                .setFromDeptId(deptId)
                .setRemark("库存加" + count)
                .setCount(count)
                .setStatus(1) // 使用常量或枚举
                .setId(null).setCreateTime(LocalDateTime.now())
                .setUpdateTime(null);
        return secAccountDO;
    }
}